package com.xinggq.user.service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xinggq.user.api.dto.UserInfoDTO;
import com.xinggq.user.api.dto.VerifyPasswordRequest;
import com.xinggq.user.api.dto.VerifyPasswordResponse;
import com.xinggq.user.service.entity.SysUserEntity;
import com.xinggq.user.service.mapper.SysUserMapper;
import com.xinggq.user.service.service.UserAuthService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

/**
 * 用户认证服务实现类
 *
 * @author xinggq
 * @since 2025-10-20
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserAuthServiceImpl implements UserAuthService {

  /** 邮箱分隔符 */
  private static final String AT_SYMBOL = "@";

  /**
   * 登录标识类型枚举
   */
  private enum LoginIdentifierType {
    /** 邮箱登录 */
    EMAIL,
    /** 手机号登录 */
    PHONE,
    /** 用户名登录 */
    USERNAME
  }

  /**
   * 用户状态常量
   */
  private static final class UserStatus {

    /** 用户状态：正常 */
    private static final int ACTIVE = 1;
  }

  /**
   * 正则表达式常量
   */
  private static final class RegexPatterns {

    /** 邮箱格式正则表达式 */
    private static final String EMAIL_PATTERN = "^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$";
    /** 手机号格式正则表达式（中国大陆手机号） */
    private static final String PHONE_PATTERN = "^1\\d{10}$";
  }

  /**
   * 错误消息常量
   */
  private static final class ErrorMessages {

    private static final String USER_NOT_FOUND = "用户不存在";
    private static final String USER_DISABLED = "用户已被禁用";
    private static final String PASSWORD_INCORRECT = "密码错误";
  }

  private final SysUserMapper sysUserMapper;
  private final PasswordEncoder passwordEncoder;

  /**
   * 验证用户密码
   * 支持用户名、邮箱、手机号三种登录方式
   *
   * @param request 密码验证请求
   * @return 密码验证响应
   */
  @Override
  public VerifyPasswordResponse verifyPassword(VerifyPasswordRequest request) {
    String loginIdentifier = request.getUsername();
    log.debug("验证用户密码，登录标识: {}", loginIdentifier);

    // 查找用户
    SysUserEntity user = findUserByLoginIdentifier(loginIdentifier);

    // 用户不存在
    if (user == null) {
      log.warn("用户不存在，登录标识类型: {}", getLoginIdentifierType(loginIdentifier));
      return VerifyPasswordResponse.fail(ErrorMessages.USER_NOT_FOUND);
    }

    // 检查用户状态
    if (!isUserActive(user)) {
      return VerifyPasswordResponse.fail(ErrorMessages.USER_DISABLED);
    }

    // 验证密码
    if (verifyUserPassword(user, request.getPassword())) {
      log.info("用户密码验证成功，用户ID: {}", user.getId());

      // 更新最后登录时间
      user.setLastLoginTime(LocalDateTime.now());
      sysUserMapper.updateById(user);
      log.info("已更新用户最后登录时间，用户ID: {}", user.getId());

      // 使用实体类的toUserInfoDTO方法转换用户信息
      UserInfoDTO userInfo = user.toUserInfoDTO();
      return VerifyPasswordResponse.success(user.getId(), userInfo);
    } else {
      log.warn("用户密码验证失败，用户ID: {}", user.getId());
      return VerifyPasswordResponse.fail(ErrorMessages.PASSWORD_INCORRECT);
    }
  }

  /**
   * 根据登录标识查找用户
   *
   * @param loginIdentifier 登录标识（用户名/邮箱/手机号）
   * @return 用户实体，如果未找到则返回null
   */
  private SysUserEntity findUserByLoginIdentifier(String loginIdentifier) {
    // 判断登录标识类型并查询
    LoginIdentifierType identifierType = getLoginIdentifierType(loginIdentifier);
    LambdaQueryWrapper<SysUserEntity> queryWrapper = new LambdaQueryWrapper<>();
    return switch (identifierType) {
      case EMAIL -> {
        log.debug("尝试通过邮箱查询用户");
        queryWrapper.eq(SysUserEntity::getEmail, loginIdentifier);
        yield sysUserMapper.selectOne(queryWrapper);
      }
      case PHONE -> {
        log.debug("尝试通过手机号查询用户");
        queryWrapper.eq(SysUserEntity::getPhone, loginIdentifier);
        yield sysUserMapper.selectOne(queryWrapper);
      }
      default -> {
        log.debug("尝试通过用户名查询用户");
        queryWrapper.eq(SysUserEntity::getUsername, loginIdentifier);
        yield sysUserMapper.selectOne(queryWrapper);
      }
    };
  }

  /**
   * 判断登录标识类型
   *
   * @param loginIdentifier 登录标识
   * @return 标识类型枚举
   */
  private LoginIdentifierType getLoginIdentifierType(String loginIdentifier) {
    // 邮箱格式：包含@且有.com/.cn等后缀
    if (loginIdentifier != null && loginIdentifier.contains(AT_SYMBOL) &&
        loginIdentifier.matches(RegexPatterns.EMAIL_PATTERN)) {
      return LoginIdentifierType.EMAIL;
    }

    // 手机号格式：1开头的11位数字
    if (loginIdentifier != null && loginIdentifier.matches(RegexPatterns.PHONE_PATTERN)) {
      return LoginIdentifierType.PHONE;
    }

    // 默认为用户名
    return LoginIdentifierType.USERNAME;
  }

  /**
   * 检查用户是否处于活跃状态
   *
   * @param user 用户实体
   * @return 是否活跃
   */
  private boolean isUserActive(SysUserEntity user) {
    if (user.getStatus() != UserStatus.ACTIVE) {
      log.warn("用户已被禁用，用户ID: {}", user.getId());
      return false;
    }
    return true;
  }

  /**
   * 验证密码
   *
   * @param user 用户实体
   * @param password 待验证的密码
   * @return 密码是否匹配
   */
  private boolean verifyUserPassword(SysUserEntity user, String password) {
    return passwordEncoder.matches(password, user.getPasswordHash());
  }
}